import json
from urllib.parse import parse_qs

from channels.generic.websocket import AsyncWebsocketConsumer

from HomeAutoAI.common.utils.Utils import get_user_from_token
from ..service.DeviceService import DeviceService
from ..service.OpenAIService import OpenAIRunService
from HomeAutoAI.common.utils.ContextVar import get_cur_user

class FunctionCallingConsumers(AsyncWebsocketConsumer):
    """
    流程:发送指令->解析指令->执行方法调用->返回结果（使用一个Assistant一个run完成）
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.thread_id = None
        self.assistant_id = None

    async def connect(self):
        # 解析query_string中的参数,这里因为一个会话对应一个thread，所以thead_id从query_string中获取
        query_string = self.scope['query_string'].decode()
        query_params = parse_qs(query_string)
        self.thread_id = query_params.get('thread_id', [''])[0]
        print(f'连接中，获得会话thread-id: {self.thread_id}')
        print(f'FunctionCallingConsumers 连接成功！')
        await self.accept()

    async def disconnect(self, code):
        print(f'FunctionCallingConsumers 断开连接！')
        await self.close()

    async def receive(self, text_data=None, bytes_data=None):
        """
        接收到消息后，转发给对应的函数处理
        :param text_data:
        :param bytes_data:
        :return:
        """
        print(f'FunctionCallingConsumers 接收到消息：{text_data}')
        data = json.loads(text_data)
        command = data.get('command_message')
        print(f'FunctionCallingConsumers 接收到命令：{command}')
        await self.run_function_calling(command_data=data)
        print(f'FunctionCallingConsumers 接受消息处理完成！')

    async def run_function_calling(self, command_data):
        """
        执行函数调用
        :param command_data:
        :return:
        """
        command_message = command_data.get('command_message')
        # 这里用户的指令可能针对不同的对象，如@某设备，某房间，所以这里需要根据指令的对象来确定Assistant
        # 这里暂时让前端直接传Assistant id,实际情况不能这样
        self.assistant_id = command_data.get('assistant_id')
        # 获取token key
        query_string = self.scope['query_string'].decode()
        query_params = parse_qs(query_string)
        token_key = query_params.get('token_key', [''])[0]
        # token_key = self.scope['query_string'].decode('utf-8').split('=')[1]
        print("token_key", token_key)
        user = get_cur_user()
        if user is not None:
            print(f'user: {user}')
            await OpenAIRunService.arun_with_func_consumer(
                thread_id=self.thread_id,
                assistant_id=self.assistant_id,
                message=command_message,
                consumer=self,
                user_id=user.user_id
            )


class FunctionCallingConsumers_v2(AsyncWebsocketConsumer):
    """
    流程:发送指令->解析指令->发送指令到OpenAI->执行方法调用->返回结果（使用两个Assistant两个run完成）
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.thread_id = None
        self.assistant_parser_id = None
        # 可传递，先写死了用于测试
        self.assistant_caller_id = "asst_moq7STjGvKAEELWjhyCYsHzJ"

    async def connect(self):
        # 解析query_string中的参数,这里因为一个会话对应一个thread，所以thead_id从query_string中获取
        query_string = self.scope['query_string'].decode()
        query_params = parse_qs(query_string)
        self.thread_id = query_params.get('thread_id', [''])[0]
        print(f'连接中，获得会话thread-id: {self.thread_id}')
        print(f'FunctionCallingConsumers 连接成功！')
        await self.accept()

    async def disconnect(self, code):
        print(f'FunctionCallingConsumers 断开连接！')
        await self.close()

    async def receive(self, text_data=None, bytes_data=None):
        """
        接收到消息后，转发给对应的函数处理
        :param text_data:
        :param bytes_data:
        :return:
        """
        print(f'FunctionCallingConsumers 接收到消息：{text_data}')
        data = json.loads(text_data)
        command = data.get('command_message')
        print(f'FunctionCallingConsumers 接收到命令：{command}')
        await self.run_function_calling(command_data=data)
        print(f'FunctionCallingConsumers 接受消息处理完成！')

    async def run_function_calling(self, command_data):
        """
        执行函数调用
        :param command_data:
        :return:
        """
        # 测试方法是不是非本地不可
        device_service = DeviceService()
        oneNET_device_control = device_service.oneNET_device_control

        command_message = command_data.get('command_message')
        # 这里用户的指令可能针对不同的对象，如@某设备，某房间，所以这里需要根据指令的对象来确定Assistant
        # 这里暂时让前端直接传Assistant id,实际情况不能这样
        self.assistant_parser_id = command_data.get('assistant_id')
        # 获取token key
        query_string = self.scope['query_string'].decode()
        query_params = parse_qs(query_string)
        token_key = query_params.get('token_key', [''])[0]
        # token_key = self.scope['query_string'].decode('utf-8').split('=')[1]
        print("token_key", token_key)

        user = get_cur_user()
        if user is not None:
            print(f'user: {user}')
            parsed_command: str = await OpenAIRunService.aparse_command(
                thread_id=self.thread_id,
                assistant_id=self.assistant_parser_id,
                message=command_message,
                user_id=user.user_id,
                consumer=self
            )


        #使用http请求调用方法
        # async with httpx.AsyncClient() as client:
        #     try:
        #         csrf_response = await client.get('http://localhost:8000/AI/csrf/get_token')
        #         response_data = csrf_response.json()
        #         csrf_token = response_data['csrfToken']
        #         client.cookies.set('csrfToken', csrf_token)
        #         headers = {
        #             'Content-Type': 'application/json',
        #             'X-CSRFToken': csrf_token
        #         }
        #
        #         if parsed_command:
        #             command_data["message"] = command_message + ":" + parsed_command.__str__()
        #             command_data["user_id"] = user.user_id
        #             command_data["assistant_id"] = self.assistant_caller_id
        #             command_data["thread_id"] = self.thread_id
        #             response = await client.post(
        #                 'http://localhost:8000/AI/llm/function_call',
        #                 json=command_data,
        #                 headers=headers
        #             )
        #             response.raise_for_status()
        #             print(f"异步请求成功:{response.json()}")
        #             run_id = response.json()['run_id']
        #             client.cookies.set('currentRun_id', run_id)
        #             cancelled_run = await OpenAIService.cancel_run(run_id=run_id, thread_id=self.thread_id)
        #             print(f"请求成功后，取消上一个任务:{cancelled_run}")
        #             return response.json()
        #         else:
        #             print(f"指令解析失败")
        #     except httpx.HTTPError as e:
        #         print(e)
        #         print(f"异步请求失败:{e.__str__()}")
        #         # print(f"指令解析失败:{response.json()}")
        #         # cancelled_run = await OpenAIService.cancel_run(run_id=run_id, thread_id=self.thread_id)
        #         # print(f"请求失败后，取消上一个任务:{cancelled_run}")
        #         return {'error': str(e)}

        print("任务完成")